﻿//创建时间: 2011-07-21
//创建作者: 李 城
//功能说明: 执行C#语句 主要用于模板语法里
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Text.RegularExpressions;
using System.CodeDom.Compiler;
using System.Reflection;

/*
 * 
 *   2011.07.21 lcheng 执行模板语法里经过解析后的可执行的c#语句 
 *     模板语法解析的可执行的c#语句主要包含
 *             &&  ||
 *            + - * /  %
 *            >  >=   <  <=  !  !=   ==
 *    ComplexBool:   必须含有 && 或 || 
 *                   不能包含 " ( )
 *    SingleBool:   仅仅比较两个数的大小  > <  !=  >=    <=   ==
 *    
 * 
*/
namespace TRPOP.Common
{
    /// <summary>
    /// 执行C#代码
    /// </summary>
    public static class ExcuteCsharpString
    {
        /// <summary>
        /// 执行c#字符串
        /// </summary>
        /// <param name="strExpression"></param>
        /// <param name="blnExcute"></param>
        /// <returns></returns>
        public static object Execute(string strExpression, ref bool blnExcute)
        {
            if (string.IsNullOrEmpty(strExpression))
            {
                blnExcute = false;
                return string.Empty;
            }
            object blnReturn = null;
            ExecuteType oExecuteType = CheckExecuteType(strExpression);
            switch (oExecuteType)
            {
                case  ExecuteType.ExecuteByComplier:
                    blnReturn =  ExecuteByComplier(strExpression,ref blnExcute);
                    break;
                case  ExecuteType.ExecuteSingleBool:
                    blnExcute = true;
                    blnReturn =  SingleBool(strExpression);
                    break;
                case ExecuteType.ExecuteComplexBool:
                    blnExcute = true;
                    blnReturn =  ComplexBool(strExpression);
                    break;
                default:
                    blnReturn =  ExecuteByComplier(strExpression, ref blnExcute);
                    break;
            }
            return blnReturn;
        }

        #region c#执行字符串的分类判断
        /// <summary>
        /// 执行c#语句的分类
        /// </summary>
        private enum ExecuteType
        {
            /// <summary>
            /// 采用动态编译的形式
            /// </summary>
            ExecuteByComplier=0,
            /// <summary>
            ///  并 或 运算,但是不能包含 ( )
            /// </summary>
            ExecuteComplexBool = 1,
            /// <summary>
            /// 计算: 大于 小于 大于等于 小于等于 不等于 等于 不进行加减乘除等运算 可进行取模运算
            /// </summary>
            ExecuteSingleBool=2
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="strExpression"></param>
        /// <returns></returns>
        private static ExecuteType CheckExecuteType(string strExpression)
        {
            if( !strExpression.Contains("(") &&
                !strExpression.Contains(")") &&
                !strExpression.Contains("+") &&!strExpression.Contains("-") &&!strExpression.Contains("*") &&!strExpression.Contains("/")
              )
            {
                if(strExpression.Contains("&&") || strExpression.Contains("||"))
                    return ExecuteType.ExecuteComplexBool;
                else if(strExpression.Contains(">") || strExpression.Contains("<")||strExpression.Contains("!")||strExpression.Contains("=="))
                {
                    return ExecuteType.ExecuteSingleBool;
                }
            }
            return ExecuteType.ExecuteByComplier;
        }
        #endregion

        #region 具体执行c#语句的方法

        /// <summary>
        ///  并 或  的运算
        /// </summary>
        /// <param name="strExpression"></param>
        /// <returns></returns>
        private static bool ComplexBool(string strExpression)
        {
            if (!strExpression.Contains("&&") && !strExpression.Contains("||"))
                return false;
            string[] strArray = strExpression.Split(new string[] { "&&", "||" }, StringSplitOptions.RemoveEmptyEntries);
            if (strExpression.Contains("&&"))
            {
                foreach (string strTemp in strArray)
                {
                    if (!SingleBool(strTemp))
                        return false;
                }
                return true;
            }
            else // ||
            {
                foreach (string strTemp in strArray)
                {
                    if (SingleBool(strTemp))
                        return true;
                }
                return false;
            }
        }

        /// <summary>
        /// 计算: 大于 小于 大于等于 小于等于 不等于 等于
        /// 不进行加减乘除等运算 暂支持取模运算 
        /// 例如: 1==2  1!=2
        /// </summary>
        /// <param name="strExpression">传进来的必须符合： A 操作符 B 的形式，A和B为单一的不含运算的字符串</param>
        /// <returns></returns>
        private static bool SingleBool(string strExpression)
        {
            string strFirstVar = string.Empty;
            string strSecondVar = string.Empty;
            string[] strArray ;
            // != ==
            if (strExpression.Contains("!=") || strExpression.Contains("=="))
            {
                strArray = strExpression.Split(new string[] { "!=", "==" }, StringSplitOptions.RemoveEmptyEntries);
            }
            // >  < >= <=
            else if (strExpression.Contains("<") || strExpression.Contains(">"))
            {
                strArray = strExpression.Split(new string[] { "<=", ">=" }, StringSplitOptions.RemoveEmptyEntries);
                if (strArray.Length < 2)
                    strArray = strExpression.Split(new string[] { "<", ">" }, StringSplitOptions.RemoveEmptyEntries);
            }
            else
                strArray = new string[] { "" };
            if (strArray.Length == 2)
            {
                strFirstVar = BaseArithmetic(strArray[0].Trim());
                strSecondVar = BaseArithmetic(strArray[1].Trim());
                bool blnEqual = string.Equals(strFirstVar, strSecondVar);
                if (strExpression.Contains("!="))
                    return !blnEqual;
                else if(strExpression.Contains("=="))
                    return blnEqual;
                double dbFirst = double.Parse(strFirstVar);
                double dbSecond = double.Parse(strSecondVar);
                if (strExpression.Contains(">="))
                {
                    return dbFirst >= dbSecond;
                }
                else if (strExpression.Contains(">"))
                {
                    return dbFirst > dbSecond;
                }
                else if (strExpression.Contains("<="))
                {
                    return dbFirst <= dbSecond;
                }
                else if (strExpression.Contains("<"))
                {
                    return dbFirst < dbSecond;
                }
            }
            return false;
        }
        /// <summary>
        /// 对表达式的基本运算
        /// </summary>
        /// <param name="strArithmetic"></param>
        /// <returns></returns>
        private static string BaseArithmetic(string strArithmetic)
        {
            if (strArithmetic.Contains("%"))
            {
                string[] strArray = strArithmetic.Split('%');
                int dbFirst = int.Parse(strArray[0].ToString().Trim());
                int intSecond = int.Parse(strArray[1].ToString().Trim());
                return (dbFirst % intSecond).ToString();
            }
            return strArithmetic;
        }

        /// <summary>
        /// 采用动态编译的方式执行C#
        /// </summary>
        /// <param name="strExpression"></param>
        /// <param name="blnExcute"></param>
        /// <returns></returns>
        private static object ExecuteByComplier(string strExpression, ref bool blnExcute)
        {
            //执行语句的详细代码
            object reobj = null;
            blnExcute = true;
            try
            {
                string strClassName = "YorkgCMSTemplateExecuteString";
                string strMethodName = "TemplateExecuteString";
                //修改php特殊的运算符
                strExpression = strExpression.Replace(".", "+");//将.转换成+
                strExpression = strExpression.Replace("'", "\"");
                //创建编译器实例  
                CodeDomProvider oComplier = CodeDomProvider.CreateProvider("C#");
                //设置编译参数 
                CompilerParameters oParas = new CompilerParameters();
                //不生成可执行文件
                oParas.GenerateExecutable = false;
                //在内存中生成输出
                oParas.GenerateInMemory = true;
                //创建动态代码   
                StringBuilder osbClassSource = new StringBuilder();
                osbClassSource.Append("public   class   " + strClassName + "\n ");
                osbClassSource.Append("{\n ");
                osbClassSource.Append("         public   object   " + strMethodName + "()\n ");
                osbClassSource.Append("         {\n ");
                osbClassSource.Append("                 return   " + strExpression + ";\n ");
                osbClassSource.Append("         }\n ");
                osbClassSource.Append("} ");
                //编译代码   
                CompilerResults oResult = oComplier.CompileAssemblyFromSource(oParas, osbClassSource.ToString());
                //获取编译后的程序集   
                Assembly assembly = oResult.CompiledAssembly;
                // 动态调用方法   
                object eval = assembly.CreateInstance(strClassName);
                MethodInfo method = eval.GetType().GetMethod(strMethodName);
                reobj = method.Invoke(eval, null);
            }
            catch (Exception ex)
            {
                blnExcute = false;
                reobj = "函数执行错误,错误信息是: " + ex.Message;
            }
            return reobj;
        }
        #endregion

    }
}
